package com.kainitram.library;

import java.sql.SQLException;

import android.content.Intent;
import android.os.Bundle;
import android.widget.Toast;

import com.actionbarsherlock.app.SherlockActivity;
import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuInflater;
import com.actionbarsherlock.view.MenuItem;
import com.j256.ormlite.android.apptools.OpenHelperManager;
import com.j256.ormlite.dao.Dao;
import com.kainitram.morm.BaseDatabaseHelper;
import com.kainitram.morm.Model;

/**
 * Base class for editing entity activity
 * 
 * @author Mino
 * 
 */
public abstract class BaseEditActivity<T extends Model> extends
		SherlockActivity {

	private BaseDatabaseHelper databaseHelper = null;
	protected T editingItem;
	protected Boolean isAddingMode;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		onCreateViewMMBase(savedInstanceState);

		Bundle extras = getIntent().getExtras();
		int itemId = extras.getInt(MMConstants.EDIT_ITEM_ID_EXTRA,
				MMConstants.NEW_ITEM_ID_DEFAULT);

		if (itemId == MMConstants.NEW_ITEM_ID_DEFAULT) {
			editingItem = createNewItem();
			isAddingMode = true;
			setTitle(getActivityCaptionWhenNewItem());
		} else {
			isAddingMode = false;
			editingItem = getItemByID(itemId);
			setTitle(getActionCaptionWhenEditItem(editingItem));
			fillViewByItem(editingItem);
		}
		
		getSupportActionBar().setHomeButtonEnabled(true);
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		MenuInflater inflater = getSupportMenuInflater();
		inflater.inflate(R.menu.edit_activity_menu, menu);
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		int menuItemID = item.getItemId();
		switch (menuItemID) {
		case android.R.id.home:
			cancel();
			return true;
		}

		if (menuItemID == R.id.editing_menu_ok) {
			onActivityOk(editingItem);
			return true;
		}

		return super.onOptionsItemSelected(item);
	}

	@Override
	protected void onDestroy() {
		super.onDestroy();

		if (databaseHelper != null) {
			OpenHelperManager.releaseHelper();
			databaseHelper = null;
		}
	}

	protected void onActivityOk(T item) {
		fillItemByView(item);

		onBeforeCommitEdit(item);
		ValidationResult result = isItemValid(item);

		if (result.isValid()) {
			onCommitEditing(item);
		} else {
			result.focusView();
		}
	}

	protected void onCommitEditing(T item) {
		try {
			Dao<T, Integer> dao = getDao();

			if (isAddingMode) {
				Integer id;
				id = dao.create(item);
				item.setID(id);
			} else {
				throw new IllegalAccessError("Este neimplementovane");
			}

			onAfterCommitEditing(item);
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			Toast toast = Toast.makeText(this, getString(R.string.edit_failed),
					Toast.LENGTH_SHORT);
			toast.show();
		}
	}

	protected void onAfterCommitEditing(T item) {
		Intent intent = new Intent();
		intent.putExtra(MMConstants.EDIT_ITEM_RESULT_ITEM_EXTRA, item);
		setResult(RESULT_OK, intent);
		finish();
	}

	/**
	 * Get database helpers
	 * 
	 * @return database helper
	 */
	public BaseDatabaseHelper getDatabaseHelper() {
		if (databaseHelper == null) {
			databaseHelper = createDatabaseHelper();
		}
		return databaseHelper;
	}

	protected void cancel() {
		setResult(RESULT_CANCELED);
		finish();
	}

	protected void onBeforeCommitEdit(T item) {
	}

	protected abstract BaseDatabaseHelper createDatabaseHelper();

	protected abstract int getActivityCaptionWhenNewItem();

	protected abstract String getActionCaptionWhenEditItem(T editingModel);

	protected abstract void onCreateViewMMBase(Bundle savedInstanceState);

	protected abstract T getItemByID(int itemID);

	protected abstract T createNewItem();

	protected abstract void fillViewByItem(T item);

	protected abstract void fillItemByView(T item);

	protected abstract Dao<T, Integer> getDao() throws SQLException;

	/**
	 * Validate item, when user confirm activity.
	 * 
	 * @param item
	 *            - item, which need valifation.
	 * @return is item valid?
	 */
	protected abstract ValidationResult isItemValid(T item);
}
